#!perl -w
#
# More Win32::API::Struct related tests
#
# $Id: 05_more_struct.t 475 2009-07-26 20:26:41Z cosimo.streppone $

use strict;
use warnings;
use Test::More;

use Win32::API::Struct;

# TODO Move to Win32::API::Struct???
use constant CHAR_SIZE => 1;
use constant WORD_SIZE => 4;

sub chars {
	my ($n) = @_;
	$n += 0;
	return $n * CHAR_SIZE;
}

sub words {
	my ($n) = @_;
	$n += 0;
	return $n * WORD_SIZE;
}

# BEGIN {
#     $Win32::API::DEBUG = 1;
# }

my $struct;
my $size;
my $test_cases = {
	empty => {
		typedef => [],
		sizeof => 0,
	},
	empty_with_spaces => {
		typedef => [ qw(  \n   \n  ) ],
		sizeof => 0,
	},
	one_word => {
		typedef => [ qw(DWORD dwSize;) ],
		sizeof  => words(1),
	},
	one_word_no_semicolon => {
		typedef => [ qw(DWORD dwSize) ],
		sizeof  => words(1),
	},
	two_words => {
		typedef => [ qw(DWORD var1; DWORD var2;) ],
		sizeof  => words(2),
	},
	three_words => {
		typedef => [ qw(DWORD var1; DWORD var2; DWORD var3;) ],
		sizeof  => words(3),
	},
	four_words => {
		typedef => [ qw(DWORD var1; DWORD var2; DWORD var3; DWORD var4;) ],
		sizeof  => words(4),
	},
	all_longs => {
		typedef => [ qw(LONG l1; LONG l2; LONG l3; LONG l4; LONG l5;) ],
		sizeof  => words(5),
	},
	mixing_longs_and_dwords => {
		typedef => [ qw(DWORD var1; LONG var2; LONG var3;) ],
		sizeof  => words(3),
	},
	# XXX Is align correct here??
	one_char => {
		typedef => [ qw(CHAR c1;) ],
		sizeof  => chars(1),
	},
	# XXX and here?
	only_chars => {
		typedef => [ qw(CHAR c1; CHAR c2; CHAR c3;) ],
		sizeof  => chars(3),
	},
	array_of_chars => {
		typedef => [ qw(CHAR array[100];) ],
		sizeof  => chars(100),
	},
	compound_1 => {
		typedef => [ qw(
			DWORD dwTest;
			CHAR szString[200];
			LONG lpDouble;
			DWORD dwTest2;
		) ],
		sizeof => words(3) + chars(200),
	},
	compound_2 => {
		typedef => [ qw(
			DWORD dwTest;
			CHAR chTest;
			CHAR szString[6];
		) ],
		sizeof => words(1) + chars(7),
		todo => 'Breaks atm',
	},
};

plan tests => 2 * scalar keys %{ $test_cases };

for my $name (sort keys %{ $test_cases }) {

	my $data = $test_cases->{$name};
	my @struct_def = @{ $data->{typedef} };
	my $align = exists $data->{align}
		? $data->{align}
		: 'auto';

	typedef Win32::API::Struct $name => @struct_def;

	$struct = new Win32::API::Struct ($name);
	ok($struct, qq{"$name" struct defined});

	if (exists $data->{todo}) {
		local $TODO = $data->{todo};
		$size = $struct->sizeof;
		is($size, $data->{sizeof}, qq{Size of struct "$name" is calculated correctly ($size)});
	}
	else {
		$size = $struct->sizeof;
		is($size, $data->{sizeof}, qq{Size of struct "$name" is calculated correctly ($size)});
	}

}

